/*
MIT License 

Copyright (c) 2021 МГТУ им. Н.Э. Баумана, кафедра ИУ-6, Михаил Фетисов, 

https://bmstu.codes/lsx/simodo
*/

#ifndef simodo_token_Lexeme
#define simodo_token_Lexeme

/*! \file Lexeme.h
    \brief Лексема абстрактного языка
*/

#include "simodo/inout/token/LexemeType.h"

#include <string>

namespace simodo::inout
{
    /*!
     * \brief Лексема языка
     *
     * Класс описывает абстрактную единицу языка - лексему. 
     * В отличие от токена (см. lsx::dsl::Token) не несёт информации о положении в тексте,
     * контексте и уточненном значении
     *
     * Значение лексемы, в отличие от Token, хранится без служебных элементов
     * (например, для аннотации хранится только строка значения, без кавычек)
     * 
     * Неизменяемый (immutable) класс (не изменяет своё состояние).
     */

    class Lexeme
    {
        std::u16string _lexeme;  ///< Строка лексемы
        LexemeType     _type = LexemeType::Empty;    ///< Тип лексемы

    public:
        Lexeme() = delete;
        Lexeme(std::u16string lexeme, LexemeType type = LexemeType::Empty)
            : _lexeme(lexeme), _type(type)
        {}

        const std::u16string & lexeme() const { return _lexeme; }
        LexemeType             type()   const { return _type; }

        /*!
         * \brief Оператор сравнения двух лексем
         * \param symbol   Лексема, которую нужно сравнить с нашей
         *
         *      Лексемы считаются совпадающими, если у них совпадают типы и содержимое.
         */
        bool operator == (const Lexeme & other) const 
        { 
            return _type == other._type && _lexeme == other._lexeme; 
        }

        /*!
         * \brief Оператор проверки лексем на неравенство
         * \param symbol   Лексема, которую нужно сравнить с нашей
         *
         *      Лексемы считаются совпадающими, если у них совпадают типы и содержимое.
         */
        bool operator != (const Lexeme & other) const 
        {
            return _type != other._type || _lexeme != other._lexeme;
        }

        /*!
         * \brief Оператор сравнения двух лексем на <
         * \param symbol   Лексема, которую нужно сравнить с нашей
         */
        bool operator < (const Lexeme & other) const 
        { 
            return (_type < other._type || (_type == other._type && _lexeme < other._lexeme)); 
        }
    };

    /*!
     * \brief Возвращает мнемоническое обозначение лексемы в зависимости от её типа
     * \param lex Лексема
     * \return Мнемоническое обозначение лексемы в зависимости от её типа
     */
    std::string getLexemeMnemonic(const Lexeme & lex);
}

#endif // simodo_token_Lexeme
